#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# account_dialog.py 
#
#  Copyright (c) 2007 INdT (Instituto Nokia de Technologia)
#                2007 Kenneth Christiansen
#
#  Author: Kenneth Rohde Christiansen <kenneth.christiansen@gmail.com>
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation; either version 2 of the
#  License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#  USA

import pygtk
pygtk.require("2.0")
import gtk
import gobject
import pango
import tapioca
import icon_theme
import os
import sys
from conversation_buffer import ConversationBuffer

from xml.etree import ElementTree

(
LOG_USER_ID,
LOG_USER_ALIAS
) = range(2)

class LogViewWindow(gobject.GObject):

    def __init__(self, main_app, local_contact_store):
        self.logs = {}
        self.main_app = main_app
        self.local_contact_store = local_contact_store
        self.last_search = []

        self.conversation_buffer = ConversationBuffer(self.main_app.emoticons)

        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("Previous Conversations")
        self.window.resize(650, 450)

        self.main_table = gtk.Table(2, 2, False)
        self.window.add(self.main_table)
        self.main_table.set_border_width(6)

        self.logview_align = gtk.Alignment(0.5, 0.5, 1, 1)
        self.main_table.attach(self.logview_align, 1, 2, 1, 2, \
                xoptions=gtk.EXPAND|gtk.FILL, \
                yoptions=gtk.EXPAND|gtk.FILL, xpadding=0, ypadding=0)
        self.logview_align.set_padding(0, 6, 3, 6)

        self.scrolled_logview = gtk.ScrolledWindow(None, None)
        self.logview_align.add(self.scrolled_logview)
        self.scrolled_logview.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
        self.scrolled_logview.set_shadow_type(gtk.SHADOW_IN)

        self.logview = gtk.TextView(self.conversation_buffer.get_text_buffer())
        self.scrolled_logview.add(self.logview)
        self.logview.set_wrap_mode(gtk.WRAP_WORD) 
        self.logview.connect("motion-notify-event", self.on_logview_motion_notify_event)

        self.left_pane_align = gtk.Alignment(0.5, 0.5, 1, 1)
        self.main_table.attach(self.left_pane_align, 0, 1, 1, 2, \
                xoptions=gtk.FILL, \
                yoptions=gtk.FILL, xpadding=0, ypadding=0)
        self.left_pane_align.set_padding(0, 6, 6, 3)

        self.left_vbox = gtk.VBox(False, 6)
        self.left_pane_align.add(self.left_vbox)

        self.scrolled_contact_list = gtk.ScrolledWindow(None, None)
        self.left_vbox.pack_start(self.scrolled_contact_list, True, True, 0)
        self.scrolled_contact_list.set_size_request(100, -1)
        self.scrolled_contact_list.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
        self.scrolled_contact_list.set_shadow_type(gtk.SHADOW_IN)

        self.contact_treeview = gtk.TreeView()
        self.scrolled_contact_list.add(self.contact_treeview)
        self.contact_treeview.set_headers_visible(False)

        self.contact_column = gtk.TreeViewColumn("Contacts")
        self.contact_treeview.set_headers_visible(False)
        self.contact_treeview.append_column(self.contact_column)

        cell_text = gtk.CellRendererText()
        cell_text.set_property('ellipsize', pango.ELLIPSIZE_END)
        self.contact_column.pack_start(cell_text, True)
        self.contact_column.add_attribute(cell_text, "markup", LOG_USER_ALIAS)

        self.contact_store = gtk.ListStore (str, str)

        self.contact_treeview.set_model(self.contact_store)
        self.contact_treeview.connect("cursor-changed", self.on_contact_selected)

        self.calendar = gtk.Calendar()
        self.left_vbox.pack_start(self.calendar, False, True, 0)
        self.calendar.display_options(gtk.CALENDAR_SHOW_HEADING|gtk.CALENDAR_SHOW_DAY_NAMES)
        self.calendar.connect("day-selected", self.on_day_selected)
        self.calendar.connect("month-changed", self.on_month_changed)

        self.search_box = gtk.HBox(False, 0)
        self.main_table.attach(self.search_box, 1, 2, 0, 1, \
                xoptions=gtk.FILL, \
                yoptions=gtk.FILL, xpadding=0, ypadding=0)
        self.search_box.set_border_width(6)

        self.search_image_align = gtk.Alignment(0.5, 0.5, 1, 1)
        self.search_box.pack_start(self.search_image_align, False, False, 0)
        self.search_image_align.set_padding(0, 0, 0, 6)

        pixbuf = icon_theme.icon_theme_get_default().load_icon("gtk-find", 22, 0)
        self.search_image = gtk.Image()
        self.search_image.set_from_pixbuf(pixbuf)
        self.search_image_align.add(self.search_image)

        self.search_entry = gtk.Entry()
        self.search_entry.connect('changed', self.on_search_entry_changed)
        self.search_box.pack_start(self.search_entry, True, True, 0)

        self.window.show_all()

        self.load_logs()
        self.add_logs()

        iter = self.contact_store.get_iter_first()
        if iter != None:
            self.contact_treeview.get_selection().select_iter(iter)
            self.on_contact_selected(self.contact_treeview)


    def load_logs(self):
        log_dir = os.path.expanduser(os.environ.get('HOME')) + '/.ereseva/logs'

        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

        for id in os.listdir(log_dir):
            path = os.path.join(log_dir, id)
            self.logs[id] = []

            if os.path.isdir(path):
                for date_str in os.listdir(path):
                    filepath = os.path.join(path, date_str)

                    year = date_str[:4]
                    month = date_str[4:6]
                    day = date_str[6:8]

                    self.logs[id].append((year, month, day, filepath))


    def add_logs(self):
        for id in self.logs:
            alias = id

            try:
                alias = self.local_contact_store.get_alias(id)
            except KeyError, e:
                alias = id

            self.contact_store.append([id, alias])


    def on_month_changed(self, calendar):
        self.calendar.clear_marks()

        self.on_contact_selected(self.contact_treeview)


    def on_contact_selected(self, treeview):
        liststore, iter = self.contact_treeview.get_selection().get_selected()

        self.calendar.clear_marks()

        if liststore.iter_is_valid(iter):
            id = liststore.get(iter, LOG_USER_ID)[0]

            for item in self.logs[id]:
                year1, month1, day1, filename = item
                year2, month2, day2 = self.calendar.get_date()
                month2 = month2 + 1

                if int(year1) == int(year2) and \
                    int(month1) == int(month2):
                    self.calendar.mark_day(int(day1))

        self.on_day_selected(self.calendar)


    def on_day_selected(self, calendar):
        year, month, day = self.calendar.get_date() 
        month = month + 1

        liststore, iter = self.contact_treeview.get_selection().get_selected()
        id = liststore.get(iter, LOG_USER_ID)[0]

        log_filename = None

        for item in self.logs[id]:
            year1, month1, day1, filename = item

            if int(year1) == int(year) and \
                int(month1) == int(month) and \
                int(day1) == int(day):
                log_filename = filename

        self.conversation_buffer.set_text("")

        if log_filename != None:
            tree = ElementTree.parse(log_filename)

            for elem in tree.findall("message"):
                received = True

                if elem.get("to") == None:
                    received = True
                if elem.get("from") == None:
                    received = False

                self.insert_message(id, elem.text + "\n", received)


    def insert_message(self, id, message, received):
        if not received:
            person = 'me'
        else:
            try:
                person = self.local_contact_store.get_alias(id)
            except KeyError, e:
                person = id

            person = person.split("@")[0]
            person = person.split(" ")[0]

        iter = self.conversation_buffer.get_end_iter()

        self.conversation_buffer.insert_with_tags_by_name(iter, "%s:" % person, "bold")
        self.conversation_buffer.insert(iter, " ")
        self.conversation_buffer.detect_and_insert_special_text(message, [])


    def on_logview_motion_notify_event(self, textview, event):
        '''Change the cursor to the pointy finger when over an uri.'''
        pointer_x, pointer_y, nothing = textview.window.get_pointer()
        x, y = textview.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x, pointer_y)
        tags = textview.get_iter_at_location(x, y).get_tags()

        tag_table = textview.get_buffer().get_tag_table()

        reset_cursor = True
        for tag in tags:
            if tag == tag_table.lookup('uri'):
                reset_cursor = False
                textview.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
                break

        if reset_cursor:
            textview.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(None)

        return True


    def on_search_entry_changed(self, entry):
        self._search_text(entry.get_text().strip())
        return False


    def _search_text(self, text):
        txtbuffer = self.conversation_buffer.get_text_buffer()

        for start_iter, end_iter in self.last_search:
            txtbuffer.remove_tag_by_name('marked', start_iter, end_iter)

        self.last_search = []

        if not text:
            self.search_entry.modify_base(gtk.STATE_NORMAL, None)
            return

        start_iter, end_iter = txtbuffer.get_bounds()

        while True:
            result = start_iter.forward_search(text, gtk.TEXT_SEARCH_VISIBLE_ONLY)
            if result:
                start_iter = result[1]
                self.last_search.append((result[0], result[1]))
                txtbuffer.apply_tag_by_name('marked', result[0], result[1])
            else:
                break

        if self.last_search:
            self.search_entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#D3FFD3"))
        else:
            self.search_entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFD3D3"))


if __name__ == "__main__":
        window = LogViewWindow(None)
        gtk.main()

